package com.txc.cloud.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.txc.cloud.admin.entity.UserEntity;
import com.txc.cloud.admin.entity.UserRoleEntity;
import com.txc.cloud.admin.mapper.PermissionMapper;
import com.txc.cloud.admin.mapper.RoleMapper;
import com.txc.cloud.admin.mapper.UserMapper;
import com.txc.cloud.admin.mapper.UserRoleMapper;
import com.txc.cloud.admin.model.dto.UserDto;
import com.txc.cloud.admin.model.vo.UserDetail;
import com.txc.cloud.admin.service.IPermissionService;
import com.txc.cloud.admin.service.IRoleDeptService;
import com.txc.cloud.admin.service.IUserService;
import com.txc.common.global.exception.CustomException;
import com.txc.common.global.model.LoginUser;
import com.txc.common.global.model.SysRole;
import com.txc.common.global.result.ResultCode;
import com.txc.common.utils.jwt.RSAUtils;
import com.txc.common.utils.supply.UserContext;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author TXC
 * @since 2022-08-02
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements IUserService {
    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private IRoleDeptService roleDeptService;
    @Resource
    private IPermissionService permissionService;
    @Resource
    private UserRoleMapper userRoleMapper;

    @Override
    public LoginUser getUserDetails(String username) {
        UserEntity user = baseMapper.selectOne(Wrappers.<UserEntity>lambdaQuery().eq(UserEntity::getUsername,
                username));
        if (ObjectUtil.isNotNull(user)) {
            LoginUser userDetails = new LoginUser();
            BeanUtils.copyProperties(user, userDetails);
            List<SysRole> roles = roleMapper.getRoleByUserId(user.getId());
            roles.forEach(role -> {
                role.setPermissions(permissionMapper.getSysPermissionByRoleId(role.getId()));
                role.setDeptIds(roleDeptService.getDeptIds(role, userDetails));
            });
            userDetails.setRoles(roles);
            userDetails.setPermissions(permissionService.getUserPermissionMap(userDetails));
            return userDetails;
        }
        return null;
    }

    @Override
    public UserEntity register(UserDto userInfo) {
        UserEntity oldUser = baseMapper.selectOne(Wrappers.<UserEntity>lambdaQuery().eq(UserEntity::getUsername,
                userInfo.getUsername()));
        if (ObjectUtil.isNotNull(oldUser)) {
            throw new CustomException(ResultCode.USER_ACCOUNT_ALREADY_EXIST);
        }
        String password = RSAUtils.decrypt(userInfo.getPassword());
        userInfo.setPassword(passwordEncoder.encode(password));
        UserEntity user = new UserEntity();
        BeanUtils.copyProperties(userInfo, user);
        user.insert();
        return user;
    }

    @Override
    public UserDetail getUserDetails() {
        LoginUser loginUser = UserContext.getUser();
        if (ObjectUtil.isNotNull(loginUser)) {
            UserDetail userDetail = new UserDetail();
            BeanUtils.copyProperties(loginUser, userDetail);
            userDetail.setRoles(loginUser.getRoles().stream().map(SysRole::getCode).collect(Collectors.toList()));
            userDetail.setPermissions(loginUser.obtainPermissionsMap());
            return userDetail;
        }
        return null;
    }

    @Override
    public List<UserEntity> getUserList() {
        return baseMapper.selectUserList();
    }

    @Override
    public boolean empower(Long id, List<Long> roleIds) {
        AtomicInteger count = new AtomicInteger();
        roleIds.forEach(roleId -> {
            UserRoleEntity roleEntity = new UserRoleEntity();
            roleEntity.setRoleId(id);
            roleEntity.setRoleId(roleId);
            userRoleMapper.insert(roleEntity);
            count.getAndIncrement();
        });
        return count.get() > 0;
    }

    @Override
    public boolean editUser(Long id, UserDto userInfo) {
        UserEntity oldUser = baseMapper.selectOne(Wrappers.<UserEntity>lambdaQuery().eq(UserEntity::getId, id));
        if (ObjectUtil.isNull(oldUser)) {
            throw new CustomException(ResultCode.USER_ACCOUNT_NOT_EXIST);
        }
        if (ObjectUtil.isNotEmpty(userInfo.getPassword())) {
            String password = RSAUtils.decrypt(userInfo.getPassword());
            userInfo.setPassword(passwordEncoder.encode(password));
        }
        UserEntity user = new UserEntity();
        user.setId(id);
        BeanUtils.copyProperties(userInfo, user);
        return user.updateById();
    }
}
